[初心者向け]VPCのメインネットワークACLとサブネットのネットワークACLの関係性について
どちらが評価されるのか?
こんにちは!AWS事業本部のおつまみです。
ネットワークACLは サブネット単位で全インスタンスに適用するファイアウォール機能です。
基本的に細かいトラフィック制御はネットワークACLではなく、セキュリティグループで行うのがスタンダートな方針です。
そのため、ネットワークACLの存在についてつい忘れがちになってしまいます。
そんな中、先日お客様にこのような質問をいただきました。
VPCに「メインネットワークACL」、サブネットに「ネットワーク ACL」が割り当たっていますが、この関係はどのようになっていますでしょうか?サブネットのネットワークACL→VPCのメインネットワークACLの順で評価されるのでしょうか?
今回はこの関係性についてお伝えしたいと思います!
いきなり結論
- 順番で評価されるわけではなく、どちらか片方のみが評価される。
- VPC作成時にデフォルトの「メインネットワークACL」が自動で割り当てられる。
- サブネットには必ずいずれかのネットワーク ACLを割り当てる必要がある。
- 個別にカスタマイズした「カスタムネットワーク ACL」
- VPCの「メインネットワークACL」(設定しない場合はこっち)
AWS公式ドキュメントにも以下のように記載されています。
VPC 内の各サブネットにネットワーク ACL を関連付ける必要があります。ネットワーク ACL に明示的にサブネットを関連付けない場合、サブネットはデフォルトのネットワーク ACL に自動的に関連付けられます。
ネットワーク ACL を複数のサブネットに関連付けることができます。ただし、サブネットは一度に 1 つのネットワーク ACL にのみ関連付けることができます。サブネットとネットワーク ACL を関連付けると、以前の関連付けは削除されます。
検証してみた
どちらかのACLでのみ評価されることを確認するためにこのような構成で検証してみました。
- Public subnet 1aにはカスタムネットワークACLを割り当てる。
- インバウンドルール:PC端末からのSSH接続を拒否するよう設定
- アウトバウンドルール:PC端末へのエフェメラルポート(1024-65335)の接続を拒否するよう設定
- Public subnet 1cにネットワークACLを割り当てない。つまりVPCデフォルトのメインネットワークACLが割り当たる。
CloudFormationでの作成
上記の構成を作成するために、以下のテンプレートをCloudFormationで実行します。
template.yml
AWSTemplateFormatVersion: "2010-09-09" Description: "NetworkACL Template." Parameters: # ------------------------------------------------------------# # Common # ------------------------------------------------------------# Prefix: Type: String Default: "network-acl-test" # ------------------------------------------------------------# # Network # ------------------------------------------------------------# VpcCidr: Type: String Default: "10.0.0.0/16" PublicSubnetCidr1a: Type: String Default: "10.0.1.0/24" PublicSubnetCidr1c: Type: String Default: "10.0.2.0/24" MyIP: Type: String Default: <MyPC IPAdress> # ------------------------------------------------------------# # EC2 # ------------------------------------------------------------# EC2InstanceName: Type: String Default: "ec2" EC2InstanceAMI: Type: AWS::EC2::Image::Id Default: "ami-078296f82eb463377" # Amazon Linux 2 AMI (HVM) - Kernel 5.10, SSD Volume Type EC2InstanceInstanceType: Type: String Default: "t3.nano" EC2InstanceVolumeType: Type: String Default: "gp2" EC2InstanceVolumeSize: Type: String Default: "8" KeyName: Type: "AWS::EC2::KeyPair::KeyName" Resources: # ------------------------------------------------------------# # VPC # ------------------------------------------------------------# Vpc: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Sub ${Prefix}-vpc # ------------------------------------------------------------# # InternetGateway # ------------------------------------------------------------# InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: ${Prefix}-InternetGateway # ------------------------------------------------------------# # VPCとInternetGatewayの関連付け # ------------------------------------------------------------# InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref Vpc # ------------------------------------------------------------# # PublicSubnet # ------------------------------------------------------------# PublicSubnet1a: Type: AWS::EC2::Subnet Properties: CidrBlock: !Ref PublicSubnetCidr1a VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1a Tags: - Key: Name Value: !Sub ${Prefix}-public-subnet-1a PublicSubnet1c: Type: AWS::EC2::Subnet Properties: CidrBlock: !Ref PublicSubnetCidr1c VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1c Tags: - Key: Name Value: !Sub ${Prefix}-public-subnet-1c # ------------------------------------------------------------# # PublicRouteTable # ------------------------------------------------------------# PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref Vpc Tags: - Key: Name Value: !Sub "${Prefix}-table" # ------------------------------------------------------------# # SubnetとRoutetableの関連付け # ------------------------------------------------------------# PublicSubnetTableAssociation1a: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1a RouteTableId: !Ref PublicRouteTable PublicSubnetTableAssociation1c: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1c RouteTableId: !Ref PublicRouteTable # ------------------------------------------------------------# # Routeの指定 # ------------------------------------------------------------# PublicRoute: Type: AWS::EC2::Route Properties: DestinationCidrBlock: 0.0.0.0/0 RouteTableId: !Ref PublicRouteTable GatewayId: !Ref InternetGateway # ------------------------------------------------------------# # SecurityGroup # ------------------------------------------------------------# EC2SecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: VpcId: !Ref Vpc SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref MyIP GroupName: !Sub "${Prefix}-sg" GroupDescription: "-" Tags: - Key: "Name" Value: !Sub "${Prefix}-sg" # ------------------------------------------------------------# # NetworkACL # ------------------------------------------------------------# NetworkAcl: Type: AWS::EC2::NetworkAcl Properties: VpcId: !Ref Vpc Tags: - Key: Name Value: !Sub ${Prefix}-public-nacl # NACLの関連付け NaclAssoc: Type: AWS::EC2::SubnetNetworkAclAssociation Properties: NetworkAclId: !Ref NetworkAcl SubnetId: !Ref PublicSubnet1a # インバウンドルール # MyIPからのSSH接続を拒否 NaclEntryInbound01: Type: AWS::EC2::NetworkAclEntry Properties: Egress: false RuleNumber: 100 RuleAction: deny Protocol: 6 PortRange: From: 22 To: 22 CidrBlock: !Ref MyIP NetworkAclId: !Ref NetworkAcl # すべて許可 NaclEntryInbound02: Type: AWS::EC2::NetworkAclEntry Properties: Egress: false RuleNumber: 110 RuleAction: allow Protocol: -1 CidrBlock: 0.0.0.0/0 NetworkAclId: !Ref NetworkAcl # アウトバウンドルール # MyIPへのエフェメラルポート接続を拒否 NaclEntryOutbound01: Type: AWS::EC2::NetworkAclEntry Properties: Egress: true RuleNumber: 100 RuleAction: deny Protocol: 6 PortRange: From: 1024 To: 65535 CidrBlock: !Ref MyIP NetworkAclId: !Ref NetworkAcl # すべて許可 NaclEntryOutbound02: Type: AWS::EC2::NetworkAclEntry Properties: Egress: true RuleNumber: 110 RuleAction: allow Protocol: -1 CidrBlock: 0.0.0.0/0 NetworkAclId: !Ref NetworkAcl # ------------------------------------------------------------# # EC2Instance # ------------------------------------------------------------# EC2Instance1a: Type: "AWS::EC2::Instance" Properties: Tags: - Key: Name Value: !Sub "${Prefix}-${EC2InstanceName}-1a" ImageId: !Ref EC2InstanceAMI KeyName: !Ref KeyName InstanceType: !Ref EC2InstanceInstanceType NetworkInterfaces: - AssociatePublicIpAddress: "true" DeviceIndex: "0" SubnetId: !Ref PublicSubnet1a GroupSet: - !Ref EC2SecurityGroup UserData: !Base64 | #! /bin/bash yum update -y EC2Instance1c: Type: "AWS::EC2::Instance" Properties: Tags: - Key: Name Value: !Sub "${Prefix}-${EC2InstanceName}-1c" ImageId: !Ref EC2InstanceAMI KeyName: !Ref KeyName InstanceType: !Ref EC2InstanceInstanceType NetworkInterfaces: - AssociatePublicIpAddress: "true" DeviceIndex: "0" SubnetId: !Ref PublicSubnet1c GroupSet: - !Ref EC2SecurityGroup UserData: !Base64 | #! /bin/bash yum update -y
設定状況の確認
期待通りの設定がされているか確認します。
VPCにはメインネットワークACLacl-0278c5e4691872389
が割り当たっています。
メインネットワークACLacl-0278c5e4691872389
を選択すると、1cのサブネットが関連づけられていることがわかります。
1cは明示的にサブネットを指定していないため、VPCにはメインネットワークACLが割り当たっています。
インバウンドルール・アウトバウンドルールはデフォルトですべてのトラフィックが許可されています。
次に1aのサブネットに関連づけられているネットワークACLを確認します。
CloudFormationで作成したカスタムネットワークACLnetwork-acl-test-public-nacl
が関連づけられていることがわかります。
インバウンドルール・アウトバウンドルールは下記の通り設定されています。
- インバウンドルール:PC端末からのSSH接続を拒否するよう設定
- アウトバウンドルール:PC端末へのエフェメラルポート(1024-65335)の接続を拒否するよう設定
接続確認
PC端末からsshで接続できるか確認してみます。
- PublicSubnet1a側のEC2インスタンスのパブリックIP:54.250.206.108
- PublicSubnet1c側のEC2インスタンスのパブリックIP:54.250.91.171
予想通り1a側のEC2には接続できませんでしたが、1c側のEC2インスタンスには接続できました!
最後に
今回はVPCのメインネットワークACLとサブネットのネットワーク ACLの関係性についてご紹介しました。
普段ネットワークACLを触る機会が少ないので、勉強になりました。
最後までお読みいただきありがとうございました!
どなたかのお役に立てれば幸いです。
以上、おつまみ(@AWS11077)でした!